package all.util;

import com.alibaba.dubbo.common.logger.Logger;
import com.alibaba.dubbo.common.logger.LoggerFactory;
import com.alibaba.dubbo.common.utils.StringUtils;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.config.utils.ReferenceConfigCache;
import com.alibaba.dubbo.rpc.service.GenericService;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;

/**
 * @auther: Griftt wu
 * @date: 2019/9/17
 **/

public class DubboServiceFactory {

    public static Logger logger = LoggerFactory.getLogger(DubboServiceFactory.class);
    private ApplicationConfig application;
    private RegistryConfig registry;
    private String version;

    private static class SingletonHolder {
        private static DubboServiceFactory INSTANCE = new DubboServiceFactory();
    }

    public static DubboServiceFactory getInstance() {
        return SingletonHolder.INSTANCE;
    }

    private DubboServiceFactory() {
        ApplicationConfig applicationConfig = new ApplicationConfig();
        applicationConfig.setName("rent-gateway");
        applicationConfig.setVersion("1.0");
        // 这里配置了dubbo的application信息*(demo只配置了name)*，因此demo没有额外的dubbo.xml配置文件
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("106.52.22.169:2181");
        registryConfig.setFile("/tmp/dubbo.cachr");
        // 这里配置dubbo的注册中心信息，因此demo没有额外的dubbo.xml配置文件
        this.application = applicationConfig;
        this.registry = registryConfig;
    }

    public Object genericInvoke(String interfaceClass, String methodName, String parameterType, Object param) {
        ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
        reference.setApplication(application);
        reference.setRegistry(registry);
        reference.setVersion(version);
        reference.setInterface(interfaceClass); // 接口名
        reference.setGeneric(true); // 声明为泛化接口
        // ReferenceConfig实例很重，封装了与注册中心的连接以及与提供者的连接，
        // 需要缓存，否则重复生成ReferenceConfig可能造成性能问题并且会有内存和连接泄漏。
        // API方式编程时，容易忽略此问题。
        // 这里使用dubbo内置的简单缓存工具类进行缓存
        ReferenceConfigCache cache = ReferenceConfigCache.getCache();
        GenericService genericService = cache.get(reference);
        if (genericService == null) {
            cache.destroy(reference);
            throw new IllegalStateException("服务不可用");
        }

        if (parameterType == null) {
            return genericService.$invoke(methodName, new String[] {}, new Object[] {});
        }
        return genericService.$invoke(methodName, new String[] { parameterType }, new Object[] { param });
    }


}